<?php
namespace Api\Controller;
use Think\Controller; 

class PayController extends Controller {
  	
  	private $conf = array(
  		'wechat'	=>	array(
	  		'appid' => "wx9ec9195e80e812da",
	        'mch_id' => "1502288031",
	        'api_key' => "a0ea023a3bea4a172f327896490c31af", 
	        'notify_url' => 'http://www.yuzhuli.com/api.php/Pay/notify',
  		),
  		'alipay'	=>	array(
  			'notify_url'	=>	'http://www.yuzhuli.com/api.php/Pay/ali_notify',
			'return_url'	=>	'http://mov30.weixinzjit.com/V3/Alipay/returnurl',
			'seller_email'	=>	'13524625822@139.com',
			'partner'	=>	'2088031711750913', 
			'key'		=>	'lo1napa166wkv3m5r10clhbu81zmb6gh',
			'privateKey' => '/home/www/www.yuzhuli.com/cert/rsa_private_key.pem',
			'publicKey' => '/home/www/www.yuzhuli.com/cert/rsa_public_key.pem', 
  		),
  	);
  	
	function _initialize() {
		header("Access-Control-Allow-Origin:*");
	    header("Access-Control-Allow-Headers:X-Requested-With"); 
	}
	
	public function getPayParm(){
		$type = I('get.type');
		$ordercode = I('get.ordercode');
		switch ($type) {
			case 'alipay':
				$this->getAlipayParm();
				break;
			case 'weixin_h5':// h5
				
				break;
			case 'weixin':// 微信网页
				break;
			default:
				$this->getWechatParm();
				break;
		}
	}
	
	public function getWechatParm(){
		Vendor("Pay.Wxpay.WxPayHelper");  
		//获取订单数据

		$orderBody = '商品名称';
		$tade_no = date('Ymd_His_').mt_rand(1000,9999);
		$attach = 'nicky_123'; 
		$total_fee = 1;
		
		$WxPayHelper = new \WxPayHelper($this->conf['wechat']);
		$response = $WxPayHelper->getPrePayOrder($orderBody, $tade_no, $total_fee, $attach);
		$data = $WxPayHelper->getOrder($response['prepay_id']);
  
		$return_data = array(
			's'	=>	true,
			'm'	=>	'参数获取成功',
			'd'	=>	$data,
		);
		$this->ajaxReturn($return_data);
		exit();
	}

	/**
	* 待完善 支付完成通知接口
	* @return
	*/
	public function notify(){
		Vendor("Pay.Wxpay.WxPayHelper");
		$WxPayHelper = new \WxPayHelper([]);
		$data = $WxPayHelper->xmlstr_to_array(file_get_contents("php://input"));
		if($data['result_code']=='SUCCESS'){
			if($data['return_code'] == 'SUCCESS'){
				$res = $this->updateOrderStatus($data['out_trade_no']);
				trace($data, 'WXPAY');
				if($res['s']){
					exit($WxPayHelper->arrayToXml(['return_code'=>'SUCCESS', 'return_msg'=>'OK']));
				}
			}
		}
		exit($WxPayHelper->arrayToXml(['return_code'=>'ERROR', 'return_msg'=>'失败']));
	}

    public function ali_notify(){
    	require_once 'ThinkPHP/Library/Vendor/autoload.php';
        $pay = new \Common\Util\Pay();
        $data = $pay->ali()->notify(\Payment\Config::ALI_CHARGE);
        if($data){
            exit('success');
        }else{
            trace('支付宝通知失败：', 'ALIPAY');
            trace($pay->errMsg(), 'ALIPAY');
            exit('fail');
        }
    }

    public function wap_ali_notify()
    {
    	require_once 'ThinkPHP/Library/Vendor/autoload.php';
        $pay = new \Common\Util\Pay();
		$alipay = C('alipay');
        $data = $pay->ali([
            'use_sandbox'               => false,// 是否使用沙盒模式
            'app_id'                    => $alipay['wap']['app_id'],
            'sign_type'                 => 'RSA2',// RSA  RSA2
            // ！！！注意：如果是文件方式，文件中只保留字符串，不要留下 -----BEGIN PUBLIC KEY----- 这种标记
            // 可以填写文件路径，或者密钥字符串  当前字符串是 rsa2 的支付宝公钥(开放平台获取)
            'ali_public_key'            => $alipay['wap']['ali_public_key'],
            // 可以填写文件路径，或者密钥字符串  我的沙箱模式，rsa与rsa2的私钥相同，为了方便测试
            'rsa_private_key'           => $alipay['wap']['rsa_public_key'],
            // 与业务相关参数
            'notify_url'                => U('Pay/wap_ali_notify', [], true, true),
            'return_url'                => 'http://www.yuzhuli.com/h5/index.html',
            'return_raw'                => false,// 在处理回调时，是否直接返回原始数据，默认为 true
        ])->notify(\Payment\Config::ALI_CHARGE);
        if($data){
            exit('success');
        }else{
            trace('支付宝通知失败：', 'ALIPAY');
            trace($pay->errMsg(), 'ALIPAY');
            exit('fail');
        }
    }
	
	private function updateOrderStatus($code)
	{
		return update_pay_status($code);
	}

	public function getAlipayParm(){
		$parameter = array(
			'service' => 'mobile.securitypay.pay',
			'partner' => $this->conf['alipay']['partner'],
			'_input_charset' => 'utf-8',
			'seller_id' => $this->conf['alipay']['seller_email'],
			'payment_type' => 1,
			'out_trade_no' => date('Ymd_His_').mt_rand(1000,9999),
			'subject' => '商品名称',
			'body' =>'商品详情',
			'total_fee' => 0.01,
			'notify_url' => $this->conf['alipay']['notify_url'],
		);
		$pp=$this->paraFilter($parameter);
		$ppa =$this->argSort($pp);
		$parameter['sign'] = $this->rsaSign($this->createLinkstring($ppa),$this->conf['alipay']['privateKey']);
		$parameter['sign_type'] = 'RSA';
		$aa=$this->createLinkstringUrlencode($parameter); 
		$this->ajaxReturn(array('s'=>true,'d'=>$aa));
		exit();
	}
	
	

	/**
	 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
	 * @param $para 需要拼接的数组
	 * return 拼接完成以后的字符串
	 */
	function createLinkstring($para) {
		$arg  = "";
		while (list ($key, $val) = each ($para)) {
			$arg.=$key."=".$val."&";
		}
		//去掉最后一个&字符
		$arg = substr($arg,0,count($arg)-2);

		//如果存在转义字符，那么去掉转义
		if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}

		return $arg;
	}
	/**
	 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串，并对字符串做urlencode编码
	 * @param $para 需要拼接的数组
	 * return 拼接完成以后的字符串
	 */
	function createLinkstringUrlencode($para) {
		$arg  = "";
		while (list ($key, $val) = each ($para)) {
			$arg.=$key."=".urlencode($val)."&";
		}
		//去掉最后一个&字符
		$arg = substr($arg,0,count($arg)-2);

		//如果存在转义字符，那么去掉转义
		if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}

		return $arg;
	}
	/**
	 * 除去数组中的空值和签名参数
	 * @param $para 签名参数组
	 * return 去掉空值与签名参数后的新签名参数组
	 */
	function paraFilter($para) {
		$para_filter = array();
		while (list ($key, $val) = each ($para)) {
			if($key == "sign" || $key == "sign_type" || $val == "")continue;
			else	$para_filter[$key] = $para[$key];
		}
		return $para_filter;
	}
	/**
	 * 对数组排序
	 * @param $para 排序前的数组
	 * return 排序后的数组
	 */
	function argSort($para) {
		ksort($para);
		reset($para);
		return $para;
	}
	
	/**
	 * RSA签名
	 * @param $data 待签名数据
	 * @param $private_key_path 商户私钥文件路径
	 * return 签名结果
	 */
	function rsaSign($data, $private_key_path) {
		$priKey = file_get_contents($private_key_path);
		$res = openssl_get_privatekey($priKey);
		openssl_sign($data, $sign, $res);
		openssl_free_key($res);
		//base64编码
		$sign = base64_encode($sign);
		return $sign;
	}
	
	public function getSign($parm){
		
		$privateKey = openssl_get_privatekey(file_get_contents($this->conf['privateKey']));
		$data = $parm; 
		$sign = '';
		openssl_sign($data, $sign, $privateKey, OPENSSL_ALGO_SHA1); 
		return base64_encode($sign);
		exit();
	}
	
	public function ArrayToString($arr){
		$parm = array();
		foreach($arr as $k=>$v){
			$parm[] = $k.'="'.$v.'"';
		}
		$parms = implode('&',$parm);
		return $parms;
	}
	

	
    /**
     * 获取返回时的签名验证结果
     * @param $para_temp 通知返回来的参数数组
     * @param $sign 返回的签名结果
     * @return 签名验证结果
     */
	function getSignVeryfy($para_temp, $sign) {
		//除去待签名参数数组中的空值和签名参数
		$para_filter = $this->paraFilter($para_temp); 
		//对待签名参数数组排序
		$para_sort = $this->argSort($para_filter); 
		//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
		$isSgin = false;
		$isSgin = $this->rsaVerify($this->createLinkstring($para_sort), trim($this->conf['publicKey']), $sign);
		
		return $isSgin;
	}

	/**
	 * RSA验签
	 * @param $data 待签名数据
	 * @param $ali_public_key_path 支付宝的公钥文件路径
	 * @param $sign 要校对的的签名结果
	 * return 验证结果
	 */
	function rsaVerify($data, $ali_public_key_path, $sign)  {
		$pubKey = file_get_contents($ali_public_key_path);
	    $res = openssl_get_publickey($pubKey);
	    $result = (bool)openssl_verify($data, base64_decode($sign), $res);
	    openssl_free_key($res);    
	    return $result;
	}
	
}